#ifndef REGISTERVIEW_HPP
#define REGISTERVIEW_HPP

#include <QDockWidget>
#include <QTableWidgetItem>
#include <QTimer>
#include <QMap>
#include <QBrush>
#include <QMapIterator>
#include <QDebug>
#include <math.h>

#include "register.hpp"

namespace Ui {
    class RegisterView;
}

/**
* @brief
*
* @class RegisterView registerview.hpp "registerview.hpp"
*/
class RegisterView : public QDockWidget {
    Q_OBJECT
public:
    /**
    * @brief
    *
    * @fn RegisterView
    * @param parent
    */
    RegisterView(QWidget *parent = 0);

    /**
    * @brief
    *
    * @fn ~RegisterView
    */
    ~RegisterView();

    void setHighlighting(bool state);

protected:
    /**
    * @brief
    *
    * @fn changeEvent
    * @param e
    */
    void changeEvent(QEvent *e);

private:
    Ui::RegisterView *ui;
    QMap<int, QTableWidgetItem*> itemsBank0;
    QMap<int, QTableWidgetItem*> itemsBank1;
    QMap<QTableWidgetItem*, QTimer*> changedTimerMap;
    bool initializing;
    bool highlightingState;

    /**
    * @brief Initialize the Bank TableView
    *
    * @fn initializeView
    */
    void initializeView();

    void setTimer(QTableWidgetItem *item);

public slots:
    /**
    * @brief Slot is called when the internal data of an Register changed
    *
    * @fn onRegisterChanged
    * @param reg
    */
    void onRegisterChanged(Register *reg);

    /**
    * @brief Slot is called when the Bank has been changed by the program
    *
    * @fn onBankChanged
    * @param bank
    */
    void onBankChanged(bool bank);

    /**
    * @brief Slot is called when programCounter has been changed
    *
    * @fn onProgramCounterChanged
    * @param programCounter
    */
    void onProgramCounterChanged(int programCounter);

private slots:
    /**
    * @brief The content of a Cell has changed
    * @details Update the internal Register data to this value
    *
    * @fn on_tbl_bank0_cellChanged
    * @param row
    * @param column
    */
    void on_tbl_bank0_cellChanged(int row, int column);

    /**
    * @brief The content of a Cell has changed
    * @details Update the internal Register data to this value
    *
    * @fn on_tbl_bank1_cellChanged
    * @param row
    * @param column
    */
    void on_tbl_bank1_cellChanged(int row, int column);

    /**
    * @brief Slot triggered when the Timer expires
    *
    * @fn onChangedTimerExpires
    */
    void onChangedTimerExpires();

    /**
    * @brief Slot triggered when Port A Bits checked or unchecked
    *
    * @fn onCbPortaStateChanged
    * @param state
    */
    void onCbPortaStateChanged(int state);

    /**
    * @brief Slot triggered when Port B Bits checked or unchecked
    *
    * @fn onCbPortbStateChanged
    * @param state
    */
    void onCbPortbStateChanged(int state);

    void onCbTrisaStateChanged(int state);

    void onCbTrisbStateChanged(int state);

    void on_cb_status_5_stateChanged(int state);

signals:
    /**
    * @brief Signal is emitted to request a change of the data of an Register
    *
    * @fn requestChangeRegister
    * @param address
    * @param bank
    * @param value
    */
    void requestChangeRegister(int address, int value);
    void requestChangeBank(bool bank);
};

#endif // REGISTERVIEW_HPP
